package com.tma.timesheettracker.contentprovider;

import java.text.ParseException;
import java.util.Date;
import java.util.ArrayList;
import java.util.List;
import com.tma.timesheettracker.model.Task;
import com.tma.timesheettracker.model.TrackingEntry;
import com.tma.timesheettracker.model.User;
import com.tma.timesheettracker.util.Util;

import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.util.Log;

public class TimeTrackerContentProvider extends ContentProvider {

	public static final String PROVIDER_NAME = "com.tma.timesheettraker";

	public static final Uri USER_URI = Uri.parse("content://" + PROVIDER_NAME
			+ "/user");
	public static final Uri TASK_URI = Uri.parse("content://" + PROVIDER_NAME
			+ "/task");
	public static final Uri TrackingEntry_URI = Uri.parse("content://"
			+ PROVIDER_NAME + "/trackingentry");
	public static final Uri TrackingEntry_Current_Date_URI = Uri
			.parse("content://" + PROVIDER_NAME + "/trackingentry/currentday");
	public static final Uri TrackingEntry_History_Day_URI = Uri
			.parse("content://" + PROVIDER_NAME + "/trackingentry/history");
	public static final Uri TASK_NAME_URI = Uri.parse("content://"
			+ PROVIDER_NAME + "/task/taskname");
	public static final int USER = 1;
	public static final int TASK = 2;
	public static final int TASK_NAME = 9;
	public static final int TASK_ID = 3;
	public static final int TRACKINGENTRY = 4;
	public static final int TRACKINGENTRY_DATE_WITH_TASK_ID = 5;
	public static final int TRACKINGENTRY_CURRENT_DAY = 6;
	public static final int TRACKINGENTRY_HISTORY_DAY = 7;
	public static final int TRACKINGENTRY_ID = 8;
	private static String m_taskName = "";
	private TimeTrackerDatabase database;

	public static final UriMatcher URI_MATCHER;

	static {
		URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
		URI_MATCHER.addURI(PROVIDER_NAME, "trackingentry", TRACKINGENTRY);
		URI_MATCHER.addURI(PROVIDER_NAME, "trackingentry/#", TRACKINGENTRY_ID);
		URI_MATCHER.addURI(PROVIDER_NAME, "trackingentry/currentday/#",
				TRACKINGENTRY_DATE_WITH_TASK_ID);
		URI_MATCHER.addURI(PROVIDER_NAME, "trackingentry/currentday",
				TRACKINGENTRY_CURRENT_DAY);
		URI_MATCHER.addURI(PROVIDER_NAME, "trackingentry/history",
				TRACKINGENTRY_HISTORY_DAY);
		URI_MATCHER.addURI(PROVIDER_NAME, "user", USER);
		URI_MATCHER.addURI(PROVIDER_NAME, "task", TASK);
		URI_MATCHER.addURI(PROVIDER_NAME, "task/taskname", TASK_NAME);
		URI_MATCHER.addURI(PROVIDER_NAME, "task/#", TASK_ID);
	}

	@Override
	public boolean onCreate() {
		database = new TimeTrackerDatabase(getContext());
		return false;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
		int uriType = URI_MATCHER.match(uri);
		String currentDay;
		switch (uriType) {
		case TASK_ID:
			queryBuilder.setTables(TimeTrackerDatabase.TABLE_TASK);
			queryBuilder
					.appendWhere(TimeTrackerContentProvider.TaskTable.TASKID
							+ "=" + uri.getLastPathSegment());
			break;

		case TASK:
			queryBuilder.setTables(TimeTrackerDatabase.TABLE_TASK);
			break;

		case TASK_NAME:
			queryBuilder.setTables(TimeTrackerDatabase.TABLE_TASK);
			queryBuilder
					.appendWhere(TimeTrackerContentProvider.TaskTable.TASKNAME
							+ " LIKE '" + m_taskName + "'");
			break;

		case USER:
			queryBuilder.setTables(TimeTrackerDatabase.TABLE_USER);
			break;

		case TRACKINGENTRY:
			queryBuilder.setTables(TimeTrackerDatabase.TABLE_TRACKING_ENTRY);
			queryBuilder
					.appendWhere(TimeTrackerContentProvider.TrackingEntryTable.USERID
							+ " ='" + Util.DEFAULT_USER_ID + "'");
			break;

		case TRACKINGENTRY_DATE_WITH_TASK_ID:
			queryBuilder.setTables(TimeTrackerDatabase.TABLE_TRACKING_ENTRY);
			currentDay = selectionArgs[0];
			queryBuilder
					.appendWhere(TimeTrackerContentProvider.TrackingEntryTable.TASK_ID
							+ "="
							+ uri.getLastPathSegment()
							+ " And "
							+ TimeTrackerContentProvider.TrackingEntryTable.DATE
							+ " LIKE '"
							+ currentDay
							+ "' And "
							+ TimeTrackerContentProvider.TrackingEntryTable.USERID
							+ " ='" + Util.DEFAULT_USER_ID + "'");
			break;

		case TRACKINGENTRY_CURRENT_DAY:
			queryBuilder.setTables(TimeTrackerDatabase.TABLE_TRACKING_ENTRY);
			currentDay = selectionArgs[0];
			Log.v("currentday", currentDay);
			queryBuilder
					.appendWhere(TimeTrackerContentProvider.TrackingEntryTable.DATE
							+ " LIKE '"
							+ currentDay
							+ "' And "
							+ TimeTrackerContentProvider.TrackingEntryTable.USERID
							+ " ='" + Util.DEFAULT_USER_ID + "'");
			break;
		case TRACKINGENTRY_HISTORY_DAY:
			queryBuilder.setTables(TimeTrackerDatabase.TABLE_TRACKING_ENTRY);
			queryBuilder
					.appendWhere(TimeTrackerContentProvider.TrackingEntryTable.DATE
							+ " < DATE('NOW') And "
							+ TimeTrackerContentProvider.TrackingEntryTable.USERID
							+ " ='" + Util.DEFAULT_USER_ID + "'");
			break;

		default:
			break;
		}
		Cursor cursor = queryBuilder.query(database.getWritableDatabase(),
				projection, selection, selectionArgs, null, null, sortOrder);
		return cursor;
	}

	@Override
	public String getType(Uri uri) {
		return null;
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		int uriType = URI_MATCHER.match(uri);
		SQLiteDatabase sqlDB = database.getWritableDatabase();
		long id;
		switch (uriType) {
		case USER:
			id = sqlDB.insert(TimeTrackerDatabase.TABLE_USER, null, values);
			break;
		case TASK:
			id = sqlDB.insert(TimeTrackerDatabase.TABLE_TASK, null, values);
			break;
		case TRACKINGENTRY:
			id = sqlDB.insert(TimeTrackerDatabase.TABLE_TRACKING_ENTRY, null,
					values);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}
		return Uri.parse(TimeTrackerDatabase.TABLE_TASK + "/" + id);
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		int uriType = URI_MATCHER.match(uri);
		SQLiteDatabase sqlDB = database.getWritableDatabase();
		int deletedRows = 0;
		switch (uriType) {
		case TASK:
			deletedRows = sqlDB.delete(TimeTrackerDatabase.TABLE_TASK,
					selection, selectionArgs);
			break;
		case USER:
			deletedRows = sqlDB.delete(TimeTrackerDatabase.TABLE_USER,
					selection, selectionArgs);
			break;
		case TRACKINGENTRY:
			deletedRows = sqlDB.delete(
					TimeTrackerDatabase.TABLE_TRACKING_ENTRY, selection,
					selectionArgs);
			break;
		case TRACKINGENTRY_ID:
			deletedRows = sqlDB.delete(
					TimeTrackerDatabase.TABLE_TRACKING_ENTRY,
					TimeTrackerContentProvider.TrackingEntryTable.ID + "="
							+ uri.getLastPathSegment(), selectionArgs);
		default:
			break;
		}
		return deletedRows;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		int uriType = URI_MATCHER.match(uri);
		int row = 0;
		SQLiteDatabase sqlDB = database.getWritableDatabase();
		switch (uriType) {
		case TRACKINGENTRY_ID:
			String id = uri.getLastPathSegment();
			row = sqlDB.update(TimeTrackerDatabase.TABLE_TRACKING_ENTRY,
					values, TimeTrackerContentProvider.TrackingEntryTable.ID
							+ "=" + id, null);
			break;

		default:
			break;
		}
		return row;
	}

	public static class UserTable {
		public static final String USERID = "user_id";
		public static final String USERNAME = "username";
		public static final String PASSWORD = "password";

		public static ContentValues toContentValues(User user) {
			ContentValues value = new ContentValues();
			value.put(USERNAME, user.getUsername());
			value.put(PASSWORD, user.getPassword());
			return value;
		}

	}

	public static class TrackingEntryTable {
		public static final String ID = "id";
		public static final String USERID = "user_id";
		public static final String TASK_ID = "task_id";
		public static final String DATE = "date";
		public static final String DURATION = "duration";

		public static ContentValues toContentValues(TrackingEntry entry) {
			ContentValues value = new ContentValues();
			value.put(USERID, entry.getUser_id());
			value.put(TASK_ID, entry.getTask_id());
			value.put(DATE, Util.dfm.format(entry.getDate()));
			value.put(DURATION, entry.getDuration());
			return value;
		}

		@SuppressWarnings("deprecation")
		public static TrackingEntry fromCursor(Cursor cursor) {
			TrackingEntry entry = new TrackingEntry();
			if (cursor.moveToFirst()) {
				entry.setId(cursor.getInt(cursor.getColumnIndex(ID)));
				Log.v("Entry Date", entry.getId() + entry.getUser_id() + "");
				entry.setTask_id(cursor.getInt(cursor.getColumnIndex(TASK_ID)));
				entry.setUser_id(cursor.getInt(cursor.getColumnIndex(USERID)));
				entry.setDate(new Date(cursor.getString(cursor
						.getColumnIndex(DATE))));
				entry.setDuration(cursor.getInt(cursor.getColumnIndex(DURATION)));
			}
			return entry;
		}

		public static List<TrackingEntry> getEntries(
				ContentResolver contentResolver, String currentDay) {
			Cursor cursor = null;

			List<TrackingEntry> lstEntry = new ArrayList<TrackingEntry>();
			try {
				cursor = contentResolver.query(TrackingEntry_Current_Date_URI,
						null, "?", new String[] { currentDay }, null);
				buildTrackingEntries(cursor, lstEntry);
			} finally {
				if (cursor != null)
					cursor.close();
			}
			return lstEntry;
		}

		public static List<TrackingEntry> getHistoricalEntries(
				ContentResolver contentResolver) throws ParseException {
			Cursor cursor = null;
			List<TrackingEntry> lstEntry = new ArrayList<TrackingEntry>();
			try {
				cursor = contentResolver.query(TrackingEntry_History_Day_URI,
						null, null, null,
						TimeTrackerContentProvider.TrackingEntryTable.DATE
								+ " DESC");
				buildTrackingEntries(cursor, lstEntry);
			} finally {
				if (cursor != null)
					cursor.close();
			}
			return lstEntry;
		}

		public static void buildTrackingEntries(Cursor cursor,
				List<TrackingEntry> lstEntry) {
			while (cursor.moveToNext()) {
				TrackingEntry entry = new TrackingEntry();
				entry.setId(cursor.getInt(cursor.getColumnIndex(ID)));
				entry.setUser_id(cursor.getInt(cursor.getColumnIndex(USERID)));
				entry.setTask_id(cursor.getInt(cursor.getColumnIndex(TASK_ID)));
				try {
					entry.setDate(Util.dfm.parse((cursor.getString((cursor
							.getColumnIndex(DATE))))));
				} catch (ParseException e) {
					Log.e("Date Parser :", "Invalid date passed in db");
				}
				entry.setDuration(cursor.getInt(cursor.getColumnIndex(DURATION)));
				lstEntry.add(entry);
			}
		}

		public static TrackingEntry getEntry(ContentResolver contentResolver,
				String currentDay, int taskId) {
			Cursor cursor = null;
			TrackingEntry entry = new TrackingEntry();
			try {
				cursor = contentResolver.query(ContentUris.withAppendedId(
						TrackingEntry_Current_Date_URI, taskId), null, "?",
						new String[] { currentDay }, null);
				entry = fromCursor(cursor);
			} finally {
				if (cursor != null)
					cursor.close();
			}
			return entry;
		}

		public static void insertEntry(ContentResolver contentResolver,
				TrackingEntry entry) {
			contentResolver.insert(TrackingEntry_URI, toContentValues(entry));
		}

		public static void updateEntry(ContentResolver contentResolver,
				TrackingEntry entry) {
			contentResolver.update(ContentUris.withAppendedId(
					TrackingEntry_URI, entry.getId()), toContentValues(entry),
					null, null);
		}

		public static int deleteEntry(ContentResolver contentResolver,
				int entryId) {
			return contentResolver.delete(
					ContentUris.withAppendedId(TrackingEntry_URI, entryId),
					null, null);
		}
	}

	public static class TaskTable {
		public static final String TASKID = "task_id";
		public static final String TASKNAME = "name";

		public static ContentValues toContentValues(Task task) {
			ContentValues value = new ContentValues();
			value.put(TASKNAME, task.getName());
			return value;
		}

		public static Task getTask(ContentResolver resolver, int taskId) {
			Task task = new Task();
			Cursor cursor = null;
			try {
				cursor = resolver.query(
						ContentUris.withAppendedId(TASK_URI, taskId), null,
						null, null, null);
				if (cursor.moveToFirst()) {
					task.setName(cursor.getString(cursor
							.getColumnIndex(TASKNAME)));
					task.setId(cursor.getInt(cursor.getColumnIndex(TASKID)));
				}

			} finally {
				if (cursor != null) {
					cursor.close();
				}
			}
			return task;
		}

		public static Task getTask(ContentResolver resolver, String taskName) {
			Task task = new Task();
			m_taskName = taskName;
			Cursor cursor = null;
			try {
				cursor = resolver.query(TASK_NAME_URI, null, null, null, null);
				if (cursor.moveToFirst()) {
					task.setName(cursor.getString(cursor
							.getColumnIndex(TASKNAME)));
					Log.v("Tsak name current", task.getName());
					task.setId(cursor.getInt(cursor.getColumnIndex(TASKID)));
				}

			} finally {
				if (cursor != null) {
					cursor.close();
				}
			}
			return task;
		}

		public static List<Task> getTasks(ContentResolver resolver) {
			List<Task> listTask = new ArrayList<Task>();
			Cursor cursor = null;
			try {
				cursor = resolver.query(TimeTrackerContentProvider.TASK_URI,
						null, null, null, null);
				while (cursor.moveToNext()) {
					Task task = new Task();
					task.setName(cursor.getString(cursor
							.getColumnIndex(TASKNAME)));
					task.setId(cursor.getInt(cursor.getColumnIndex(TASKID)));
					listTask.add(task);
				}
			} finally {
				if (cursor != null) {
					cursor.close();
				}

			}

			return listTask;
		}

		public static Uri insert(ContentResolver resolver, Task task) {
			return resolver.insert(TimeTrackerContentProvider.TASK_URI,
					toContentValues(task));
		}
	}

}
